package ca.uvic.group2.server;

import ca.uvic.group2.ServerFactory;
import ca.uvic.group2.api.*;
import ca.uvic.group2.api.exceptions.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.*;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.Hashtable;
import java.util.StringTokenizer;
import org.apache.log4j.*;


public class QuoteServerImpl extends UnicastRemoteObject implements QuoteServer, RemoteServer, QuoteCache.QuoteFetcher {

    private static Category debugLog = Logger.getInstance("QuoteServDebug");
    //private static Category perfLog = Logger.getInstance("QuotePerf");

    private String _serverName = "QuoteServer";
    private AuditLog logger;
    private String serverId="QuoteServer";
    private QuoteCache quoteCacher;
    

    public QuoteServerImpl() throws RemoteException, CommException {
        super();
        logger = new ServerFactory().getAuditServer();
	quoteCacher = new QuoteCache(debugLog);
        debugLog.debug("Constructor: QuoteServer");
    }

    //
    // RemoteServer interface
    //
    private int _port;
    public void serverStart(int port) throws RemoteException, CommException {
        debugLog.info("QuoteServer Startup on Port: " + port);
        try {
            ServerFactory.serverStart(this, port, RMI_NAME);
            _port = port;
        } catch (Exception err) {
            err.printStackTrace();
            throw new CommException(err.getMessage());
        }
    }

    public void serverStop() throws RemoteException, CommException {
        debugLog.info("QuoteServer Shutdown");
        try {

            // Perform any cleanup here.

        } catch (Exception err) {
            err.printStackTrace();
            throw new CommException(err.getMessage());
        }
    }

    public void setServerName(String name) throws RemoteException {
        _serverName = name;
    }

    public String getServerName() throws RemoteException {
        return _serverName;
    }

    public String getHostName() throws RemoteException {
        try {
            return InetAddress.getLocalHost().getHostName();
        } catch (UnknownHostException err) {
            return null;
        }
    }

    //
    // QuoteServer interface
    //
    public void initSystem() throws RemoteException {
        synchronized (quoteCacher) {
            quoteCacher.initSystem();
        }
    }


    public Quote quote(int transId, String stockSymbol, String username) throws CommException, RemoteException {
	return quoteCacher.quote(transId, 0L, stockSymbol, username, this);
    }


    // 
    // QuoteFetcher callback Interface 
    //
    public Quote fetchQuote(int transId, long sessionId, String stockSymbol, String username) throws IOException{
        debugLog.info("Legacy Quote for " + stockSymbol + ", user: " + username);
        Socket kkSocket = null;
        PrintWriter out = null;
        BufferedReader in = null;

        try {
            kkSocket = new Socket("b09.seng.engr.uvic.ca", 4442);
            out = new PrintWriter(kkSocket.getOutputStream(), true);
            in = new BufferedReader(new InputStreamReader(kkSocket.getInputStream()));
        } catch (UnknownHostException e) {
            debugLog.error("Don't know about host: b09.seng.engr.uvic.ca");
            //System.exit(1);
        } catch (IOException e) {
            debugLog.error("Couldn't get I/O for the connection Project Quote Server likely down");
            //System.exit(1);
        }

        BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
        String fromServer;
        String fromUser;

        fromUser = stockSymbol + "," + username;
        out.println(fromUser);

        fromServer = in.readLine();

        StringTokenizer stoken = new StringTokenizer(fromServer, ",");

        Quote data = new Quote();
        data.price = new Money(Double.parseDouble(stoken.nextToken()));
        data.stock = stoken.nextToken();
        data.username = stoken.nextToken();
        data.expiry = System.currentTimeMillis() + 60000;
        data.timestamp = Long.parseLong(stoken.nextToken());
        data.key = stoken.nextToken();

        out.close();
        in.close();
        stdIn.close();
        kkSocket.close();

        //Check to see if the stock returned was the one requested.
        if(!stockSymbol.equals(data.stock)) {
            debugLog.fatal("Mismatch in stock Symbol");
        }

	logger.quote(serverId, transId, data.price.doubleValue(), data.stock, data.username, data.timestamp, data.key);
        return data;
    }

}

